package irsystem.model;

import irsystem.view.IRSystemView;

public class TermWeighting {

    /* konstanta */
        private static final int RAW_TF = 0;
        private static final int LOG_TF = 1;
        private static final int BINARY_TF = 2;
        private static final int AUGMENTED_TF = 3;

    /* atribut-atribut yang dimiliki oleh kelas TermWeighting */
        private IndexTable invertedFile;
            //TF weight index file, IDF weight index file, invertedFile seluruhnya
        private java.util.Set < String > ListTerm;             //list dari term

        private boolean isDoc, isIDF, isNorm;
        private int codeTF;


    /* constructor  */
        public TermWeighting (java.util.Set < String > ListTerm, int numOfDoc, int codeTF, boolean isIDF, boolean isNorm, boolean isDoc) {
            this.isDoc = isDoc;
            this.isIDF = isIDF;
            this.isNorm = isNorm;
            this.codeTF = codeTF;
            this.ListTerm = ListTerm;
            this.invertedFile = new IndexTable(ListTerm.size(), numOfDoc);
            //this.invertedFile.clear();
            DoTermWeight();
        }

    /* getter */
        public IndexTable getInvertedFile () {
            return (this.invertedFile);
        }
        
    /* method-method lain yang dimiliki oleh kelas TermWeighting */
        private void DoTermWeight() {
            System.out.println("doTermWeight...");
            DoTermFrequency();
            if (this.isIDF && !this.isNorm) DoIDF();
            else if(this.isNorm) DoNormalization();
        }
        
        private void DoTermFrequency () {
            switch (this.codeTF) {
                case RAW_TF:
                    System.out.println("DoTermFrequency >> Raw TF...");
                    DoTermWeight_RawTF();
                    break;
                case LOG_TF:
                    System.out.println("DoTermFrequency >> Log TF...");
                    DoTermWeight_LogTF();
                    break;
                case BINARY_TF:
                    System.out.println("DoTermFrequency >> Binary TF...");
                    DoTermWeight_BinaryTF();
                    break;
                case AUGMENTED_TF:
                    System.out.println("DoTermFrequency >> Augmented TF...");
                    DoTermWeight_AugmentedTF();
                    break;
            }
        }

        private void DoTermWeight_RawTF () {
            int row = 0, column = 0;
            if (this.isDoc) {
                for (String term : ListTerm) {
                    column = 0;
                    for (document doc : IRSystemView.DC) {
                        this.invertedFile.setCell(row, column, countTerm(doc.getText(),term));
                        column++;
                    }
                    row++;
                }
            } else {
                for (String term : ListTerm) {
                    column = 0;
                    for (document doc : IRSystemView.Query) {
                        this.invertedFile.setCell(row, column, countTerm(doc.getText(),term));
                        column++;
                    }
                    row++;
                }
            }
        }
        private void DoTermWeight_BinaryTF () {
            int row = 0, column = 0;
            if (this.isDoc) {
                for (String term : ListTerm) {
                    column = 0;
                    for (document doc : IRSystemView.DC) {
                        this.invertedFile.setCell(row, column, isFound(doc.getText(), term));
                        column++;
                    }
                    row++;
                }
            } else {
                for (String term : ListTerm) {
                    column = 0;
                    for (document doc : IRSystemView.Query) {
                        this.invertedFile.setCell(row, column, isFound(doc.getText(), term));
                        column++;
                    }
                    row++;
                }
            }
        }
        private void DoTermWeight_AugmentedTF () {
            int row = 0, column = 0;
            double max_TF = 0;

            if (isDoc) {
                for (document doc : IRSystemView.DC) {
                    row = 0;
                    for (String term : ListTerm) {
                        double a = countTerm(doc.getText(),term);
                        max_TF = (max_TF < a) ? a : max_TF;
                    }

                    for (String term : ListTerm) {
                        this.invertedFile.setCell(row, column, (0.5 + (0.5 * countTerm(doc.getText(),term)/max_TF)));
                        row++;
                    }
                    column++;
                }
            } else {
                for (document doc : IRSystemView.Query) {
                    row = 0;
                    for (String term : ListTerm) {
                        double a = countTerm(doc.getText(),term);
                        max_TF = (max_TF < a) ? a : max_TF;
                    }

                    for (String term : ListTerm) {
                        if (doc.getText().contains(term))
                            this.invertedFile.setCell(row, column, (0.5 + (0.5 * countTerm(doc.getText(),term)/max_TF)));
                        else
                            this.invertedFile.setCell(row, column, 0d);
                        row++;
                    }
                    column++;
                }
            }
        }
        private void DoTermWeight_LogTF() {
            int row = 0, column = 0;

            if (this.isDoc) {
                for (String term : ListTerm) {
                    column = 0;
                    for (document doc : IRSystemView.DC) {
                        double count = countTerm(doc.getText(),term);
                        if (count == 0) this.invertedFile.setCell(row, column, (double)0);
                        else this.invertedFile.setCell(row, column, 1d + Math.log10(countTerm(doc.getText(), term)));
                        column++;
                    }
                    row++;
                }
            } else {
                for (String term : ListTerm) {
                    column = 0;
                    for (document doc : IRSystemView.Query) {
                        double count = countTerm(doc.getText(),term);
                        if (count == 0) this.invertedFile.setCell(row, column, (double)0);
                        else this.invertedFile.setCell(row, column, 1d + Math.log10(countTerm(doc.getText(), term)));
                        column++;
                    }
                    row++;
                }
            }
        }

        private void DoIDF () {
            System.out.println("doIDF...");
            int row = 0, column = 0;
            double counter = 0;
            for (String term : ListTerm) {
                column = 0;
                counter = 0;
                for (document doc : IRSystemView.DC) {
                    if (doc.getText().contains(term)) counter++;
                }
                if (counter != 0) {
                    double idf = Math.log(IRSystemView.DC.size()/counter);
                    if (this.isDoc) {
                        for (document doc : IRSystemView.DC) {
                            double weightBefore = this.invertedFile.getCell(row, column);
                            this.invertedFile.setCell(row, column, weightBefore*idf);
                            column++;
                        }
                    } else {
                        for (document doc : IRSystemView.Query) {
                            double weightBefore = this.invertedFile.getCell(row, column);
                            this.invertedFile.setCell(row, column, weightBefore*idf);
                            column++;
                        }
                    }
                }

                row++;
            }
        }

        private void DoNormalization () {
            System.out.println("doNormalization...");
            double pembilang = 1, sumKuadrat = 0;
            
            if (!this.isIDF) {
                for (int j = 0; j < invertedFile.getColumn(); ++j) {
                    sumKuadrat = 0;
                    for (int i = 0; i < invertedFile.getRow(); ++i) {
                        sumKuadrat = sumKuadrat + Math.pow(invertedFile.getCell(i, j), 2);
                    }
                    if (sumKuadrat != 0) {
                        pembilang = Math.sqrt(sumKuadrat);
                        for (int i = 0; i < invertedFile.getRow(); ++i) {
                            double value = invertedFile.getCell(i, j)/pembilang;
                            invertedFile.setCell(i, j, value);
                        }
                    }
                }
            }else {
                DoIDF();
                for (int j = 0; j < invertedFile.getColumn(); ++j) {
                    sumKuadrat = 0;
                    for (int i = 0; i < invertedFile.getRow(); ++i) {
                        sumKuadrat = sumKuadrat + Math.pow(invertedFile.getCell(i, j), 2);
                    }
                    if (sumKuadrat != 0) {
                        pembilang = Math.sqrt(sumKuadrat);
                        for (int i = 0; i < invertedFile.getRow(); ++i) {
                            double value = invertedFile.getCell(i, j)/pembilang;
                            invertedFile.setCell(i, j, value);
                        }
                    }
                }
            }
        }

        private double countTerm (java.util.List < String > docText, String Term) {
            double retval = 0;
            for (String term : docText) {
                if (term.equals(Term)) retval++;
            }
            return retval;
        }
        
        private double isFound (java.util.List < String > docText, String Term) {
            double retval = 0d;
            for (String term : docText) {
                if (term.equals(Term)) {retval = 1d; return retval;}
            }
            return retval;
        }
}
